#include <config.h>
#ifdef LANG_X86

;
; RegisterAccessors.s -- provides functions to read/write registers in the X86
;                        architecture.
;

[GLOBAL readInstructionPointer]
readInstructionPointer:
    pop eax     ; Get the return address
    jmp eax     ; return - can't use RET because return address popped off
                ; stack.

[GLOBAL writeStackPointer]
writeStackPointer:
  pop ebx
  pop eax
  mov esp, eax
  jmp ebx

[GLOBAL readStackPointer]
readStackPointer:
  mov eax, esp
  add eax, 4          ; Stack was pushed with return address, so take into account.
  ret

[GLOBAL writeBasePointer]
writeBasePointer:
  mov ebp, [esp+4]
  ret

[GLOBAL readBasePointer]
readBasePointer:
  mov eax, ebp
  ret

[GLOBAL writeBRegister]
writeBRegister:
  mov ebx, [esp+4]
  ret

[GLOBAL readBRegister]
readBRegister:
  mov eax, ebx
  ret

[GLOBAL writePageDirectory]
writePageDirectory:
  push ebp
  mov ebp, esp
  mov eax, [ebp+8]
  mov cr3, eax
  pop ebp
  ret

[GLOBAL readPageDirectory]
readPageDirectory:
  mov eax, cr3
  ret

[GLOBAL enablePaging]
enablePaging:
  push ebp
  mov ebp, esp
  mov eax, [ebp+8]
  mov eax, cr0
  or  eax, 0x80000000
  mov cr0, eax
  pop ebp
  ret

[GLOBAL stopInterrupts]
stopInterrupts:
  cli
  ret

[GLOBAL startInterrupts]
startInterrupts:
  sti
  ret

[GLOBAL getPageFaultAddress]
getPageFaultAddress:
  mov eax, cr2
  ret

[GLOBAL writeMsr]
writeMsr:
  mov edx, [esp+8]
  mov eax, [esp+12]
  mov ecx, [esp+4]
  wrmsr
  ret
  
[GLOBAL copyPagePhysical]
copyPagePhysical:
  push ebx
  pushf                 ; push EFLAGS, so we can pop it and reenable interrupts
                        ; later, if they were enabled anyway.
  cli                   ; Disable interrupts, so we aren't interrupted.
  
                        ; Load these in BEFORE we disable paging!
  mov ebx, [esp+12]      ; Source address
  mov ecx, [esp+16]     ; Destination address
  
  mov edx, cr0          ; Get the control register...
  and edx, 0x7fffffff   ; and...
  mov cr0, edx          ; Disable paging.
  
  mov edx, 1024         ; 1024*4bytes = 4096 bytes
  
.loop:
  mov eax, [ebx]        ; Get the word at the source address
  mov [ecx], eax        ; Store it at the dest address
  add ebx, 4            ; Source address += sizeof(word)
  add ecx, 4            ; Dest address += sizeof(word)
  dec edx               ; One less word to do
  jnz .loop             
  
  mov edx, cr0          ; Get the control register again
  or  edx, 0x80000000   ; and...
  mov cr0, edx          ; Enable paging.
  
  popf
  pop ebx
  ret
  
[GLOBAL flushPageDirectory]
flushPageDirectory:
  mov eax, cr3
  mov cr3, eax
  ret

#endif // LANG_X86
